#include "sal.h"
#include "ctc_cli.h"
#include "ctc_cli_common.h"
#include "ctc_debug.h"
#include "ctc_error.h"
#include "ctc_ipmc_cli.h"
#include "ctcs_api.h"

static ctc_ipmc_group_info_t asw_ipmc_group_info;


CTC_CLI(ctc_cli_asw_ipmc_add_ipv4_group,
        ctc_cli_asw_ipmc_add_ipv4_group_cmd,
        "ipmc add group-address A.B.C.D MASK_LEN vrf VRFID  ({ip-based-l2mc |} | )",
        CTC_CLI_IPMC_M_STR,
        "Add",
        "Group address class D IP address",
        CTC_CLI_IPV4_FORMAT,
        "The length of group address mask <32>",
        "VRF id or FID",
        "VRF id or FID value",
        "Do IP based L2 mcast")
{
    int32 ret  = CLI_SUCCESS;
    uint32 masklen = 0;
    uint16 vrf_id = 0;
    uint8  param_idx = 0;

    sal_memset(&asw_ipmc_group_info, 0, sizeof(ctc_ipmc_group_info_t));

    CTC_CLI_GET_IPV4_ADDRESS("ip", asw_ipmc_group_info.address.ipv4.group_addr, argv[param_idx]);
    param_idx++;

    CTC_CLI_GET_UINT8_RANGE("mask", masklen, argv[param_idx], 0, CTC_MAX_UINT8_VALUE);
    asw_ipmc_group_info.group_ip_mask_len = masklen;
    param_idx++;

    CTC_CLI_GET_UINT16_RANGE("vrf", vrf_id, argv[param_idx], 0, CTC_MAX_UINT16_VALUE);
    asw_ipmc_group_info.address.ipv4.vrfid = vrf_id;
    param_idx++;
    ret = ctcs_ipmc_add_group(g_api_lchip, &asw_ipmc_group_info);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_ipmc_remove_ipv4_group,
        ctc_cli_asw_ipmc_remove_ipv4_group_cmd,
        "ipmc remove group group-address A.B.C.D MASK_LEN vrf VRFID ip-based-l2mc",
        CTC_CLI_IPMC_M_STR,
        "Remove",
        CTC_CLI_IPMC_GROUP_DESC,
        "Group address, class D IP address",
        CTC_CLI_IPV4_FORMAT,
        "The length of group address mask <32>",
        CTC_CLI_VRFID_DESC,
        CTC_CLI_VRFID_ID_DESC,
        "Do IP based L2 mcast")
{
    int32 ret  = CLI_SUCCESS;
    uint32 masklen = 0;
    uint16 vrf_id = 0;

    sal_memset(&asw_ipmc_group_info, 0, sizeof(ctc_ipmc_group_info_t));

    CTC_CLI_GET_IPV4_ADDRESS("ip", asw_ipmc_group_info.address.ipv4.group_addr, argv[0]);

    CTC_CLI_GET_UINT8_RANGE("mask", masklen, argv[1], 0, CTC_MAX_UINT8_VALUE);
    asw_ipmc_group_info.group_ip_mask_len = masklen;

    CTC_CLI_GET_UINT16_RANGE("vrf", vrf_id, argv[2], 0, CTC_MAX_UINT16_VALUE);
    asw_ipmc_group_info.address.ipv4.vrfid = vrf_id;

    ret = ctcs_ipmc_remove_group(g_api_lchip, &asw_ipmc_group_info);

    if (ret < 0)
    {
        ctc_cli_out("%% %s :%d \n\r", ctc_get_error_desc(ret), ret);
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_ipmc_add_ipv4_member,
        ctc_cli_asw_ipmc_add_ipv4_member_cmd,
        "ipmc add member group-address A.B.C.D MASK_LEN vrf VRFID " \
        "ip-based-l2mc (" CTC_CLI_PORT_BITMAP_STR ")",
        CTC_CLI_IPMC_M_STR,
        "Add",
        CTC_CLI_IPMC_MEMBER_DESC,
        "Group address, class D IP address",
        CTC_CLI_IPV4_FORMAT,
        "The length of group address mask <32>",
        CTC_CLI_VRFID_DESC,
        CTC_CLI_VRFID_ID_DESC,
        "IP based l2 mcast",
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC
        )
{
    int32 ret  = CLI_SUCCESS;
    uint32 masklen = 0;
    uint16 vrf_id = 0;
    uint8  index = 0;

    sal_memset(&asw_ipmc_group_info, 0, sizeof(ctc_ipmc_group_info_t));

    CTC_CLI_GET_IPV4_ADDRESS("ip", asw_ipmc_group_info.address.ipv4.group_addr, argv[0]);

    CTC_CLI_GET_UINT8_RANGE("mask", masklen, argv[1], 0, CTC_MAX_UINT8_VALUE);
    asw_ipmc_group_info.group_ip_mask_len = masklen;

    CTC_CLI_GET_UINT16_RANGE("vrf", vrf_id, argv[2], 0, CTC_MAX_UINT16_VALUE);
    asw_ipmc_group_info.address.ipv4.vrfid = vrf_id; 

    CTC_CLI_PORT_BITMAP_GET(asw_ipmc_group_info.ipmc_member[0].port_bmp);

    ret = ctcs_ipmc_add_member(g_api_lchip, &asw_ipmc_group_info);

    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_ipmc_remove_ipv4_member,
        ctc_cli_asw_ipmc_remove_ipv4_member_cmd,
        "ipmc remove member group-address A.B.C.D MASK_LEN vrf VRFID " \
        "ip-based-l2mc (" CTC_CLI_PORT_BITMAP_STR ")",
        CTC_CLI_IPMC_M_STR,
        "Remove",
        CTC_CLI_IPMC_MEMBER_DESC,
        "Group address, class D IP address",
        CTC_CLI_IPV4_FORMAT,
        "The length of group address mask <32>",
        CTC_CLI_VRFID_DESC,
        CTC_CLI_VRFID_ID_DESC,
        "IP based l2 mcast",
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC
        )
{
    int32 ret  = CLI_SUCCESS;
    uint32 masklen = 0;
    uint8 index = 0;
    uint16 vrf_id = 0;

    sal_memset(&asw_ipmc_group_info, 0, sizeof(ctc_ipmc_group_info_t));

    CTC_CLI_GET_IPV4_ADDRESS("ip", asw_ipmc_group_info.address.ipv4.group_addr, argv[0]);

    CTC_CLI_GET_UINT8_RANGE("mask", masklen, argv[1], 0, CTC_MAX_UINT8_VALUE);
    asw_ipmc_group_info.group_ip_mask_len = masklen;

    CTC_CLI_GET_UINT16_RANGE("vrf", vrf_id, argv[2], 0, CTC_MAX_UINT16_VALUE);
    asw_ipmc_group_info.address.ipv4.vrfid = vrf_id;


    CTC_CLI_PORT_BITMAP_GET(asw_ipmc_group_info.ipmc_member[0].port_bmp);


    ret = ctcs_ipmc_remove_member(g_api_lchip, &asw_ipmc_group_info);

    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_ipmc_show_ipv4_group_param,
        ctc_cli_asw_ipmc_show_ipv4_group_param_cmd,
        "show ipmc group info group-address A.B.C.D MASK_LEN source-address A.B.C.D MASK_LEN vrf VRFID (ip-based-l2mc|) ",
        CTC_CLI_SHOW_STR,
        CTC_CLI_IPMC_M_STR,
        "IP multicast group",
        "Information, including source and group IP adress, etc.",
        "Group address, class D IP address",
        CTC_CLI_IPV4_FORMAT,
        "The length of group address mask <32>",
        "Source address",
        CTC_CLI_IPV4_FORMAT,
        "The length of source address mask <32>",
        CTC_CLI_VRFID_DESC,
        CTC_CLI_VRFID_ID_DESC,
        "Do IP based L2 mcast")
{
    int32 ret  = CLI_SUCCESS;
    uint32 masklen = 0;
    uint16 vrf_id = 0;
    uint8  index = 0;
    uint32 tempip = 0;
    char * buf2 ="/32";
    char buf[CTC_IPV6_ADDR_STR_LEN];
    char buf1[CTC_IPV6_ADDR_STR_LEN];

    sal_memset(&asw_ipmc_group_info, 0, sizeof(ctc_ipmc_group_info_t));

    asw_ipmc_group_info.ip_version = CTC_IP_VER_4;

    CTC_CLI_GET_IPV4_ADDRESS("ip", asw_ipmc_group_info.address.ipv4.group_addr, argv[0]);

    CTC_CLI_GET_UINT8_RANGE("mask", masklen, argv[1], 0, CTC_MAX_UINT8_VALUE);
    asw_ipmc_group_info.group_ip_mask_len = masklen;

    CTC_CLI_GET_IPV4_ADDRESS("ip", asw_ipmc_group_info.address.ipv4.src_addr, argv[2]);

    CTC_CLI_GET_UINT8_RANGE("mask", masklen, argv[3], 0, CTC_MAX_UINT8_VALUE);
    asw_ipmc_group_info.src_ip_mask_len = masklen;

    CTC_CLI_GET_UINT16_RANGE("vrf", vrf_id, argv[4], 0, CTC_MAX_UINT16_VALUE);
    asw_ipmc_group_info.address.ipv4.vrfid = vrf_id;

    index = CTC_CLI_GET_ARGC_INDEX("ip-based-l2mc");
    if (index != 0xFF)
    {
        asw_ipmc_group_info.flag |= CTC_IPMC_FLAG_L2MC;
    }

    ret = ctcs_ipmc_get_group_info(g_api_lchip, &asw_ipmc_group_info);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out( "%-21s%-21s%-6s%-6s\n", "Group-IP", "IPSA","VRF", "Port-bmp");
    ctc_cli_out("--------------------------------------------------------------\n");
    /*to get ipmc group info*/

    tempip = sal_ntohl(asw_ipmc_group_info.address.ipv4.group_addr);
    sal_inet_ntop(AF_INET, &tempip, buf1, CTC_IPV6_ADDR_STR_LEN);
    sal_strncat(buf1, buf2, 5);

    tempip = sal_ntohl(asw_ipmc_group_info.address.ipv4.src_addr);
    sal_inet_ntop(AF_INET, &tempip, buf, CTC_IPV6_ADDR_STR_LEN);
    sal_strncat(buf, buf2, 5);

    ctc_cli_out( "%-21s%-21s%-6d 0x%-6x\n", buf1,buf,asw_ipmc_group_info.address.ipv4.vrfid,asw_ipmc_group_info.ipmc_member[0].port_bmp[0]);


    return CLI_SUCCESS;
}

int32
ctc_asw_ipmc_cli_init(uint8 cli_tree_mode)
{
    install_element(cli_tree_mode, &ctc_cli_asw_ipmc_add_ipv4_group_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_ipmc_remove_ipv4_group_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_ipmc_add_ipv4_member_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_ipmc_remove_ipv4_member_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_ipmc_show_ipv4_group_param_cmd);

    return CLI_SUCCESS;
}

